package com.ezops.dao.facade;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ezops.dao.generics.dao.hibernate.GenericDAO;
import com.ezops.dto.ValidationRule;
import com.ezops.models.Asset;
import com.ezops.util.Report;
import com.ezops.util.Report.Row;

/**
 * Facade layer to manage the rules.
 * 
 * @author vgaurav
 * 
 */
@Component
public class RuleManagementFacade {

	public final static String RULEFILEDIR = System.getProperty("user.home")
			+ File.separator + "EZOPS";

	public final static String EZOPS_RULE_SET = RULEFILEDIR + File.separator
			+ File.separator + "ezopsValidation.xlsx";

	private Report rules;

	@Autowired
	private GenericDAO<Asset, Serializable> dao;

	public RuleManagementFacade() {
		try {
			rules = new Report(new File(EZOPS_RULE_SET));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Return all existing validation rules.
	 * 
	 * @return
	 */
	public List<ValidationRule> getAllValidationRules() {

		List<ValidationRule> validationRules = new ArrayList<>();
		//Map<String, Integer> assetMap = new HashMap<String, Integer>();
		Iterator<Row> rulesRow = rules.iterator();
		while (rulesRow.hasNext()) {
			Row row = rulesRow.next();
			ValidationRule validationRule = getRule(row);
			/*assetMap = createAssetMap(splitCommaSeperatedValues(validationRule
					.getAssetClass()));
			validationRule.setAllAssets(assetMap);*/
			validationRules.add(validationRule);
		}
		return validationRules;
	}

	/**
	 * Method to convert all the list item to asset Map with list value as a key
	 * and value as 0
	 * 
	 * @param assetClass
	 * @return
	 */
	private Map<String, Integer> createAssetMap(List<String> assetClass) {
		Map<String, Integer> assetMap = new HashMap<String, Integer>();
		List<Asset> allAssets = dao.findAll();
		for (Asset assets : allAssets) {
			assetMap.put(assets.getAssetName().toUpperCase(), 0);
		}
		for (String assets : assetClass) {
			if(assetMap.containsKey(assets)){
				assetMap.put(assets, 1);
			}
			/*for (Map.Entry<String, Integer> entry : assetMap.entrySet()) {
				if (assets.equals(entry.getKey())) {
					assetMap.put(entry.getKey(), 1);
				}
			}*/
		}
		return assetMap;
	}

	/**
	 * Method to convert assetClass comma separated value to list
	 * 
	 * @param value
	 * @return
	 */
	private static List<String> splitCommaSeperatedValues(String value) {
		if(value == null || value.equals("") || value.contains(",") == false){
			return Arrays.asList(value);
		}
		String[] values = value.toUpperCase().split(",");
		return Arrays.asList(values);
	}

	/**
	 * Return the validation rule applied for @param ezopsField
	 * 
	 * @param ezopsFieldName
	 * @return
	 */
	public ValidationRule getRule(String ezopsFieldName) {
		// index 0 is for the field name
		Row ruleRow = rules.lookup(0, ezopsFieldName, false);
		return getRule(ruleRow);

	}

	/**
	 * Save the given validation rules in the data source.
	 * 
	 * @param rules
	 * @return
	 */
	public boolean saveValidationRules(List<ValidationRule> validationRules) {
		// if(rules == null)

		try {
			rules.clear();

			Iterator<ValidationRule> newRules = validationRules.iterator();
			while (newRules.hasNext()) {
				Row ruleRow = rules.createRow();
				fillRow(ruleRow, newRules.next());

			}
			rules.save(EZOPS_RULE_SET);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	/**
	 * Set the rule value from @rule to @ruleRow
	 * 
	 * @param ruleRow
	 * @param next
	 */
	private void fillRow(Row ruleRow, ValidationRule rule) {
		int index = -1;
		ruleRow.setValue(++index, rule.getEzopsFieldName());
		ruleRow.setValue(++index, rule.getAssetName());
		ruleRow.setValue(++index, rule.getMandatoryName());
		ruleRow.setValue(++index, rule.getType());
		ruleRow.setValue(++index, rule.getRange());
		ruleRow.setValue(++index, rule.getDbLookupName());
		ruleRow.setValue(++index, rule.getRefColumnName());

	}

	private ValidationRule getRule(Row row) {
		ValidationRule rule = new ValidationRule();
		int index = -1;
		rule.setEzopsFieldName(row.getValue(++index));
		rule.setAssetName(row.getValue(++index));
		rule.setMandatoryName(row.getValue(++index));
		rule.setType(row.getValue(++index));
		rule.setRange(row.getValue(++index));
		return rule;

	}
}
